/*
 * protocol.h
 *
 *  Created on: 2011-7-14
 *      Author: minorityee1984@gmail.com
 *     Purpose: 協議及編解碼接口定義
 */

#ifndef PROTOCOL_H_
#define PROTOCOL_H_

#include "type_def.h"
#include "msg_def.h"
#include <string.h>

/////////////////////////////////////////////
//			數據包協議
/////////////////////////////////////////////

#define HEAD_BYTE_0		0x00
#define HEAD_BYTE_1		0xff


/////////////////////////////////////////////
//			數據包數據結構
/////////////////////////////////////////////


typedef uint8_t ClientID;
enum
{
	enmInvalidClientID = -1,
};

//打包後的數據結構宏定義
#define PACKED_PKG_HEADER_OFFSET	0
#define PACKED_PKG_HEADER_SIZE		(sizeof(Byte) * 2 + sizeof(ClientID) + sizeof(uint16_t))
#define PACKED_PKG_DATA_OFFSET		PACKED_PKG_HEADER_SIZE
//FIXME 這裡使用的MAX_MSG_BODY_SIZE並不是packed之後的大小(偏大)
#define PACKED_PKG_DATA_SIZE		MAX_MSG_BODY_SIZE

#define MAX_PACKED_PKG_SIZE			(PACKED_PKG_HEADER_SIZE + PACKED_MSG_BODY_OFFSET + PACKED_PKG_DATA_SIZE)

typedef struct tagPackageHeader
{
	Byte			headByte[2];	// 數據包頭標識符
	ClientID		clientID;		// 客戶端號
	uint16_t		dataLen;		// 數據長度
}PackageHeader;

typedef struct tagPackageBase
{
	PackageHeader	header;			// 數據包頭
	PackageData		data;			// 數據包數據
}PackageBase;

#define FILL_PACKAGE_HEADER(p, id, len)	do {	\
	(p).headByte[0] = HEAD_BYTE_0;	\
	(p).headByte[1] = HEAD_BYTE_1;	\
	(p).clientID = id;	\
	(p).dataLen = len;	\
}while(0)



#define MAX_PACKAGE_SIZE sizeof(PackageBase)
#define PACKAGE_HEADER_SIZE sizeof(PackageHeader)

#define GET_PACKAGE_SIZE(p) (GET_PACKAGE_DATA_LEN(p) + PACKAGE_HEADER_SIZE)
#define GET_PACKAGE_DATA_LEN(p) (((PackageBase*)p)->header.dataLen)
#define GET_CLIENT_ID(p) (((PackageBase*)p)->header.clientID)

//創建數據包頭
#define CREATE_PACKAGE_HEADER(NAME, CLIENTID, MSG) \
	PackageHeader NAME = {{0}}; \
	FILL_PACKAGE_HEADER(NAME, CLIENTID, sizeof(MSG));

//創建臨時數據包
#define CREATE_PACKAGE(NAME, CLIENTID, MSG) \
	PackageBase NAME;	\
	memset(&NAME, 0, sizeof(NAME));	\
	FILL_PACKAGE_HEADER(NAME, CLIENTID, sizeof(MSG));	\
	NAME.data = MSG;

//創建數據包
#define NEW_PACKAGE(pNAME, CLIENTID, MSG) \
	PackageBase *pNAME = (PackageBase*)malloc(sizeof(PackageBase)) ;	\
	memset(pNAME, 0, sizeof(PackageBase));	\
	FILL_PACKAGE_HEADER(*pNAME, CLIENTID, sizeof(PackageBase));	\
	pNAME->data = MSG;

static int find_pkg_header_byte(const Byte*, unsigned int);

int pack_msg(
				Byte				*pszBuf,
				unsigned int		uBufLen,
				unsigned int		*puOffset,
				ClientID			id,
				const Message		*pstMessage,
				unsigned int		uSizeOfMsg);

int unpack_msg(
				const Byte			*pszBuf,
				unsigned int		uBufLen,
				unsigned int		*puOffset,
				ClientID			*id,
				Message				*pstMessage,
				unsigned int		*puSizeOfMsg);

#endif /* PROTOCOL_H_ */
